import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class CollectionsApp {

    private BufferedReader reader;

    public CollectionsApp() {
        reader = new BufferedReader(new InputStreamReader((System.in)));
    }

    public void run() {
        String option;

        while (true) {
            try {
                showMenuOptions();
                option = reader.readLine();
                if (option.equals("Q") || option.equals("q"))
                    System.exit(0);

                switch (Integer.parseInt(option)) {
                    case 1:
                        runStack();
                        break;
                    case 2:
                        runPriorityQueue();
                        break;
                    case 3:
                        runHashMap();
                        break;
                    case 4:
                        runDoublyLinkedList();
                        break;
                    case 5:
                        runCircularLinkedList();
                        break;
                    case 6:
                        runAVLtree();
                        break;
                    case 7:
                        runRedBlackTree();
                        break;
                    case 8:
                        runBubbleSort();
                        break;
                    case 9:
                        runInsertionSort();
                        break;
                    case 10:
                        runsMergeSort();
                        break;
                    case 11:
                        runQuickSort();
                        break;
                    case 12:
                        runHeapSort();
                        break;
                    default:
                        System.err.println("Invalid entry. Try again.");
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            catch (NumberFormatException e) {
                System.err.println("Invalid entry. Try again.");
            }
        }
    }

    private void showMenuOptions() {
        System.out.println("\nSelect an Option");
        System.out.println("------ COLLECTIONS ------");
        System.out.println("1. Stack");
        System.out.println("2. Priority Queue");
        System.out.println("3. HashMap");
        System.out.println("4. Doubly Linked List");
        System.out.println("5. Circular Linked List");
        System.out.println("6. AVL Tree");
        System.out.println("7. Red Black Tree");
        System.out.println("--------- SORTS ---------");
        System.out.println("8. Bubble Sort");
        System.out.println("9. Insertion Sort");
        System.out.println("10. Merge Sort");
        System.out.println("11. Quick Sort");
        System.out.println("12. Heap Sort");
        System.out.println("-------------------------");
        System.out.println("Q. EXIT");
    }

    private void showQuitPrompt() {
        System.out.println("Enter Q anytime to quit");
    }

    public void runStack() {
        Stack<Integer> stack = new Stack<Integer>();

        System.out.println("---------- Stack Demo ----------");
        showQuitPrompt();

        String line;
        while (true) {
            try {
                printStackMenu();

                line = reader.readLine();
                if (line.equals("Q") || line.equals("q"))
                    break;

                switch (Integer.parseInt(line)) {
                    case 1:
                        if (stack.isEmpty())
                            System.out.println("Stack is empty");
                        else
                            System.out.println(stack.top());
                        break;
                    case 2:
                        pushToStack(stack);
                        break;
                    case 3:
                        popStack(stack);
                        break;
                    case 4:
                        System.out.println(stack.size());
                        break;
                    default:
                        System.err.println("Invalid entry. Try again.");
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            catch (NumberFormatException e) {
                System.err.println("Invalid entry. Try again.");
            }
        }
    }

    private void printStackMenu() {
        System.out.println("\n1. Print top");
        System.out.println("2. Push");
        System.out.println("3. Pop");
        System.out.println("4. Size");
    }

    private void pushToStack(Stack stack) {
        System.out.print("Enter an integer to push: ");
        try {
            int n = Integer.parseInt(reader.readLine());
            stack.push(n);
            System.out.println("Pushed " + n);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        catch (NumberFormatException e) {
            System.err.println("Not a number. Try again");
        }
    }

    private void popStack(Stack stack) {
        Integer n = (Integer) stack.pop();

        if (n == null)
            System.out.println("Nothing to pop");
        else
            System.out.println("Popped " + n + " from stack");
    }

    public void runPriorityQueue() {
        //TODO
    }

    public void runHashMap() {
        //TODO
    }

    public void runDoublyLinkedList() {
        //TODO
    }

    public void runCircularLinkedList() {
        //TODO
    }

    public void runAVLtree() {
        //TODO
    }

    public void runRedBlackTree() {
        //TODO
    }

    public void runBubbleSort() {
        System.out.println("--------- Bubble Sort ---------");

        int[] array = {4, 3, 7, -14, 0, 5, 6, -2, 9, 20, 6};
        printIntArray(array);

        array = BubbleSort.sortInts(array);
        printIntArray(array);
    }

    public void runInsertionSort() {
        System.out.println("--------- Insertion Sort ---------");

        int[] array = {4, 3, 7, -14, 0, 5, 6, -2, 9, 20, 6};
        printIntArray(array);

        array = InsertionSort.sortInts(array);
        printIntArray(array);
    }

    private void printIntArray(int[] array) {
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }

    public void runsMergeSort() {
        System.out.println("--------- Merge Sort ---------");

        int[] array = {4, 3, 7, -14, 0, 5, 6, -2, 9, 20, 6};
        printIntArray(array);

        array = MergeSort.sortInts(array);
        printIntArray(array);
    }

    public void runQuickSort() {
        //TODO
    }

    public void runHeapSort() {
        //TODO
    }

    public static void main(String[] args) {
        CollectionsApp app = new CollectionsApp();
        app.run();
    }

}
